package com.me.controller;

import com.me.annotation.Admin;
import com.me.annotation.Authorize;
import com.me.model.User;
import com.me.model.normal.NormalUser;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 吕旺平
 * @date 2019/10/20 15:58:01
 * @description
 */
public abstract class Controller {
	private static Map<String,Object> params;
	protected HttpServletRequest req;
	protected HttpServletResponse resp;
	protected HttpSession session;
	protected User u;
	
	public Controller(HttpServletRequest req, HttpServletResponse resp) {
		this.req = req;
		this.resp = resp;
		session = req.getSession();
		try {
			req.setCharacterEncoding("utf8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		u = (User)session.getAttribute("user");
	}

	protected void setRedirectParam(String key,Object value){
		setRedirectParam(key,value,false);
	}

	protected void setRedirectParam(String key,Object value,boolean reset){
		if (params == null){
			params = new HashMap<String,Object>();
		}
		if (reset){
			params.clear();
		}
		params.put(key,value);
	}

	public boolean isParamEnabled(){
		return params != null && params.size() != 0;
	}

	public void resetParam(){
		params.clear();
	}

	@Deprecated
	public abstract String excute();

	public String excute(String arg) {
		try {
			Method method = this.getClass().getMethod(arg);
			if (
					method.getAnnotation(Authorize.class) != null ||
					method.getAnnotation(Admin.class) != null||
					Controller.class.getAnnotation(Authorize.class) != null
			) {
				User u = (User) getSessionAttr("user");
				if (u == null){
					return "./user/login.jsp";
				}
				if (method.getAnnotation(Admin.class) != null && !u.isAdmin()){
					return "./index.jsp";
				}
			}

			if (isParamEnabled()){
				for (Map.Entry<String, Object> p : params.entrySet()){
					setReqAttr(p.getKey(),p.getValue());
				}
				resetParam();
			}

			return (String)method.invoke(this);
		} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
			e.printStackTrace();
		}
		return "error.jsp";
	}
	
	protected String getParam(String key){
		return req.getParameter(key);
	}

	protected boolean getBooleanParam(String key){
		return Boolean.parseBoolean(getParam(key));
	}

	protected int getIntegerParam(String key){
		return Integer.parseInt(getParam(key));
	}

	protected String[] getParams(String key){
		return req.getParameterValues(key);
	}
	
	protected Object getSessionAttr(String key){
		return session.getAttribute(key);
	}
	
	protected void setSessionAttr(String key,Object val){
		session.setAttribute(key,val);
	}
	
	protected void setReqAttr(String key,Object val){
		req.setAttribute(key,val);
	}
	
	protected Object getReqAttr(String key){
		return req.getAttribute(key);
	}
	
	protected void removeReqAttr(String key){
		req.removeAttribute(key);
	}

	protected NormalUser getSessionUser(){
		return (NormalUser)getSessionAttr("user");
	}

	protected String redirectToAction(String methodName){
		String cName = this.getClass().getSimpleName();
		return "./" + cName.substring(0,cName.indexOf("Controller")).toLowerCase() +"?state=" + methodName;
	}
}
